package com.suep.data_analysis.service;

import com.suep.data_analysis.dto.UserConfigDetailDto;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 通用属性计算器
 * 支持所有可能的属性组合和计算方式
 */
@Component
@AllArgsConstructor
public class AttributeCalculator {
    
    private final ArmamentService armamentService;
    
    /**
     * 属性类型枚举
     */
    public enum AttributeType {
        // 百分比属性
        CRIT_RATE("暴击率", true),
        CRIT_DMG("暴击伤害", true),
        ATK("攻击力", true),
        DEF("防御力", true),
        HP("生命值", true),
        PENETRATION("穿透率", true),
        ENERGY_REGEN("能量自动回复", true),
        CONTROL("异常掌控", true),
        IMPACT("冲击力", true),
        PHYSICAL("物理", true),
        ETHER("以太", true),
        FIRE("火属性", true),
        ICE("冰属性", true),
        ELECTRIC("电属性", true),
        
        // 固定值属性
        BASE_ATK("基础攻击力", false),
        MASTERY("异常精通", false),
        BASE_ENERGY_REGEN("基础能量自动回复", false),
        BASE_CONTROL("基础异常掌控", false),
        BASE_IMPACT("基础冲击力", false),
        PENETRATION_VALUE("穿透值", false),
        SMALL_ATK("小攻击力", false),
        SMALL_DEF("小防御力", false),
        SMALL_HP("小生命值", false);
        
        private final String displayName;
        private final boolean isPercentage;
        
        AttributeType(String displayName, boolean isPercentage) {
            this.displayName = displayName;
            this.isPercentage = isPercentage;
        }
        
        public String getDisplayName() {
            return displayName;
        }
        
        public boolean isPercentage() {
            return isPercentage;
        }
    }
    
    /**
     * 计算最终属性值
     * @param userConfig 用户配置
     * @param attributeType 属性类型
     * @param baseValue 基础值
     * @return 最终属性值
     */
    public double calculateAttribute(UserConfigDetailDto userConfig, AttributeType attributeType, double baseValue) {
        // 特殊属性需要特殊处理
        if (attributeType == AttributeType.ENERGY_REGEN) {
            return calculateEnergyRegen(userConfig, baseValue);
        } else if (attributeType == AttributeType.CONTROL) {
            return calculateControl(userConfig, baseValue);
        } else if (attributeType == AttributeType.IMPACT) {
            return calculateImpact(userConfig, baseValue);
        } else if (attributeType == AttributeType.PENETRATION) {
            return calculatePenetration(userConfig, baseValue);
        } else if (attributeType.isPercentage()) {
            return calculatePercentageAttribute(userConfig, attributeType, baseValue);
        } else {
            return calculateFixedAttribute(userConfig, attributeType, baseValue);
        }
    }
    
    /**
     * 计算能量回复（特殊规则）
     * 代理人原有的 + 基础能量自动回复/10 + 能量自动回复
     */
    private double calculateEnergyRegen(UserConfigDetailDto userConfig, double baseValue) {
        // 1. 代理人原有的
        double finalValue = baseValue;
        
        // 2. 基础能量自动回复/10
        double baseEnergyRegen = getCoreSkillBonus(userConfig, AttributeType.BASE_ENERGY_REGEN);
        finalValue += baseEnergyRegen / 10.0;
        
        // 3. 能量自动回复（百分比加成）
        double percentageBonus = getPercentageBonus(userConfig, AttributeType.ENERGY_REGEN);
        finalValue = finalValue * (1 + percentageBonus);
        
        return Math.round(finalValue * 100.0) / 100.0;
    }
    
    /**
     * 计算异常掌控（特殊规则）
     * (代理人原有的 + 基础异常掌控) * (1 + 异常掌控)
     */
    private double calculateControl(UserConfigDetailDto userConfig, double baseValue) {
        // 1. 代理人原有的 + 基础异常掌控
        double baseWithFixed = baseValue + getCoreSkillBonus(userConfig, AttributeType.BASE_CONTROL);
        
        // 2. 异常掌控（百分比加成）
        double percentageBonus = getPercentageBonus(userConfig, AttributeType.CONTROL);
        double finalValue = baseWithFixed * (1 + percentageBonus);
        
        return Math.round(finalValue * 100.0) / 100.0;
    }
    
    /**
     * 计算冲击力（特殊规则）
     * (代理人原有的 + 基础冲击力) * (1 + 冲击力)
     */
    private double calculateImpact(UserConfigDetailDto userConfig, double baseValue) {
        // 1. 代理人原有的 + 基础冲击力
        double baseWithFixed = baseValue + getCoreSkillBonus(userConfig, AttributeType.BASE_IMPACT);
        
        // 2. 冲击力（百分比加成）
        double percentageBonus = getPercentageBonus(userConfig, AttributeType.IMPACT);
        double finalValue = baseWithFixed * (1 + percentageBonus);
        
        return Math.round(finalValue * 100.0) / 100.0;
    }
    
    /**
     * 计算穿透率（特殊规则）
     * 代理人原有的 + 穿透率 + 穿透值总和/5
     */
    private double calculatePenetration(UserConfigDetailDto userConfig, double baseValue) {
        // 1. 代理人原有的
        double finalValue = baseValue;
        
        // 2. 穿透率（百分比加成）
        double percentageBonus = getPercentageBonus(userConfig, AttributeType.PENETRATION);
        finalValue += percentageBonus;
        
        // 3. 穿透值总和/5
        double penetrationValue = getFixedBonus(userConfig, AttributeType.PENETRATION_VALUE);
        finalValue += penetrationValue / 5.0;
        
        return Math.round(finalValue * 100.0) / 100.0; // 保持原始单位
    }
    
    /**
     * 计算百分比属性（如暴击率、攻击力等）
     */
    private double calculatePercentageAttribute(UserConfigDetailDto userConfig, AttributeType attributeType, double baseValue) {
        // 暴击率、暴击伤害直接累加所有来源
        if (attributeType == AttributeType.CRIT_RATE || attributeType == AttributeType.CRIT_DMG) {
            double total = baseValue;
            
            // 核心技加成
            total += getCoreSkillBonus(userConfig, attributeType);
            
            // 音擎副属性
            total += getArmamentSecondaryBonus(userConfig, attributeType, true);
            
            // 两件套属性（直接累加，不区分固定值和百分比）
            if (userConfig.getSetBonus() != null) {
                String[] possibleKeys = {
                    attributeType.getDisplayName(),
                    attributeType.getDisplayName() + "加成"
                };
                for (String key : possibleKeys) {
                    if (userConfig.getSetBonus().containsKey(key)) {
                        total += ((Number) userConfig.getSetBonus().get(key)).doubleValue();
                        break;
                    }
                }
            }
            
            // 驱动盘主属性（4号位和5号位）
            if (userConfig.getDriveMainAttr4() != null) {
                String key = attributeType.getDisplayName();
                if (userConfig.getDriveMainAttr4().containsKey(key)) {
                    total += ((Number) userConfig.getDriveMainAttr4().get(key)).doubleValue();
                }
            }
            if (userConfig.getDriveMainAttr5() != null) {
                String key = attributeType.getDisplayName();
                if (userConfig.getDriveMainAttr5().containsKey(key)) {
                    total += ((Number) userConfig.getDriveMainAttr5().get(key)).doubleValue();
                }
            }
            
            // 驱动盘随机属性（所有6个位置）
            total += getDriveRandomAttrBonus(userConfig, attributeType, true);
            
            if (attributeType == AttributeType.CRIT_RATE) {
                total = Math.min(1.0, total); // 暴击率上限100%
                return Math.round(total * 10000.0) / 10000.0; // 返回0.434这样的形式
            } else {
                return Math.round(total * 10000.0) / 10000.0; // 返回1.716这样的形式
            }
        }
        
        // 攻击力、防御力、生命值的特殊计算逻辑
        if (attributeType == AttributeType.ATK || attributeType == AttributeType.DEF || attributeType == AttributeType.HP) {
            // 1. 基础值 + 驱动盘主属性固定值（小攻击力、小防御力、小生命值）
            double fixedBonus = getFixedBonus(userConfig, attributeType);
            double baseWithFixed = baseValue + fixedBonus;
            
            // 2. 所有百分比加成
            double percentageBonus = getPercentageBonus(userConfig, attributeType);
            double finalValue = baseWithFixed * (1 + percentageBonus);
            
            // 3. 驱动盘随机属性固定值（小攻击力、小防御力、小生命值）
            AttributeType smallAttrType = null;
            switch (attributeType) {
                case ATK:
                    smallAttrType = AttributeType.SMALL_ATK;
                    break;
                case DEF:
                    smallAttrType = AttributeType.SMALL_DEF;
                    break;
                case HP:
                    smallAttrType = AttributeType.SMALL_HP;
                    break;
            }
            if (smallAttrType != null) {
                double smallAttrBonus = getDriveRandomAttrBonus(userConfig, smallAttrType, false);
                finalValue += smallAttrBonus;
            }
            
            return Math.round(finalValue * 100.0) / 100.0;
        }
        
        // 其他属性仍然走原有逻辑
        double fixedBonus = getFixedBonus(userConfig, attributeType);
        double baseWithFixed = baseValue + fixedBonus;
        double percentageBonus = getPercentageBonus(userConfig, attributeType);
        double finalValue = baseWithFixed * (1 + percentageBonus);
        
        return Math.round(finalValue * 100.0) / 100.0;
    }
    
    /**
     * 计算固定值属性（如异常精通、冲击力等）
     */
    private double calculateFixedAttribute(UserConfigDetailDto userConfig, AttributeType attributeType, double baseValue) {
        // 固定值属性直接相加
        double fixedBonus = getFixedBonus(userConfig, attributeType);
        double finalValue = baseValue + fixedBonus;
        
        return Math.round(finalValue * 100.0) / 100.0;
    }
    
    /**
     * 获取固定值加成
     */
    private double getFixedBonus(UserConfigDetailDto userConfig, AttributeType attributeType) {
        double bonus = 0;
        
        // 核心技加成
        bonus += getCoreSkillBonus(userConfig, attributeType);
        
        // 音擎副属性（固定值）
        bonus += getArmamentSecondaryBonus(userConfig, attributeType, false);
        
        // 两件套属性（固定值）
        bonus += getSetBonus(userConfig, attributeType, false);
        
        // 驱动盘主属性（固定值）
        if (attributeType == AttributeType.ATK || attributeType == AttributeType.DEF || attributeType == AttributeType.HP) {
            // 对于攻击力、防御力、生命值，只包含小攻击力、小防御力、小生命值的固定值
            AttributeType smallAttrType = null;
            switch (attributeType) {
                case ATK:
                    smallAttrType = AttributeType.SMALL_ATK;
                    break;
                case DEF:
                    smallAttrType = AttributeType.SMALL_DEF;
                    break;
                case HP:
                    smallAttrType = AttributeType.SMALL_HP;
                    break;
            }
            if (smallAttrType != null) {
                bonus += getDriveMainAttrBonus(userConfig, smallAttrType, false);
            }
        } else {
            bonus += getDriveMainAttrBonus(userConfig, attributeType, false);
        }
        
        // 驱动盘随机属性（固定值）
        bonus += getDriveRandomAttrBonus(userConfig, attributeType, false);
        
        return bonus;
    }
    
    /**
     * 获取百分比加成
     */
    public double getPercentageBonus(UserConfigDetailDto userConfig, AttributeType attributeType) {
        double bonus = 0;
        
        // 音擎副属性（百分比）
        bonus += getArmamentSecondaryBonus(userConfig, attributeType, true);
        
        // 两件套属性（百分比）
        bonus += getSetBonus(userConfig, attributeType, true);
        
        // 驱动盘主属性（百分比）
        bonus += getDriveMainAttrBonus(userConfig, attributeType, true);
        
        // 驱动盘随机属性（百分比）
        bonus += getDriveRandomAttrBonus(userConfig, attributeType, true);
        
        return bonus;
    }
    
    /**
     * 获取核心技加成
     */
    private double getCoreSkillBonus(UserConfigDetailDto userConfig, AttributeType attributeType) {
        if (userConfig.getCoreSkillBonus() == null) return 0;
        
        String key = attributeType.getDisplayName();
        if (userConfig.getCoreSkillBonus().containsKey(key)) {
            return ((Number) userConfig.getCoreSkillBonus().get(key)).doubleValue();
        }
        return 0;
    }
    
    /**
     * 获取音擎副属性加成
     */
    private double getArmamentSecondaryBonus(UserConfigDetailDto userConfig, AttributeType attributeType, boolean isPercentage) {
        if (userConfig.getArmamentExtraBonus() == null || userConfig.getArmamentId() == null) return 0;
        
        try {
            // 根据音擎ID查询副属性类型
            var armament = armamentService.getArmamentById(userConfig.getArmamentId());
            if (armament == null || armament.getSecondaryStatType() == null) return 0;
            
            // 检查副属性类型是否匹配
            if (armament.getSecondaryStatType().equals(attributeType.getDisplayName())) {
                // 音擎副属性除了异常精通都是百分比
                if (attributeType == AttributeType.MASTERY) {
                    // 异常精通是固定值
                    if (!isPercentage) {
                        return userConfig.getArmamentExtraBonus();
                    }
                } else {
                    // 其他属性都是百分比
                    if (isPercentage) {
                        return userConfig.getArmamentExtraBonus();
                    }
                }
            }
        } catch (Exception e) {
            // 如果查询失败，返回0
            return 0;
        }
        
        return 0;
    }
    
    /**
     * 获取两件套属性加成
     */
    private double getSetBonus(UserConfigDetailDto userConfig, AttributeType attributeType, boolean isPercentage) {
        if (userConfig.getSetBonus() == null) return 0;
        
        String key = attributeType.getDisplayName();
        if (userConfig.getSetBonus().containsKey(key)) {
            // 对于属性伤害加成，直接返回值，不区分固定值和百分比
            if (attributeType == AttributeType.PHYSICAL || attributeType == AttributeType.ETHER || 
                attributeType == AttributeType.FIRE || attributeType == AttributeType.ICE || 
                attributeType == AttributeType.ELECTRIC) {
                return ((Number) userConfig.getSetBonus().get(key)).doubleValue();
            }
            // 对于其他属性，按原有逻辑处理
            return ((Number) userConfig.getSetBonus().get(key)).doubleValue();
        }
        return 0;
    }
    
    /**
     * 获取驱动盘主属性加成
     */
    private double getDriveMainAttrBonus(UserConfigDetailDto userConfig, AttributeType attributeType, boolean isPercentage) {
        double bonus = 0;
        
        // 根据属性类型确定哪些位置有该属性
        switch (attributeType) {
            case CRIT_RATE:
            case CRIT_DMG:
            case MASTERY:
                // 4号位：暴击率、暴击伤害、异常精通
                bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr4(), attributeType.getDisplayName());
                break;
            case ATK:
            case DEF:
            case HP:
                // 攻击力、防御力、生命值在4、5、6号位都可能出现
                if (isPercentage) {
                    // 百分比加成：4、5、6号位的主属性百分比
                    bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr4(), attributeType.getDisplayName());
                    bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr5(), attributeType.getDisplayName());
                    bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr6(), attributeType.getDisplayName());
                } else {
                    // 固定值：只包含小攻击力、小防御力、小生命值
                    // 这些在getFixedBonus中单独处理
                }
                break;
            case PHYSICAL:
            case ETHER:
            case FIRE:
            case ICE:
            case ELECTRIC:
                // 5号位：以太、火属性、冰属性、电属性、物理
                bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr5(), attributeType.getDisplayName());
                break;
            case IMPACT:
            case CONTROL:
                // 6号位：冲击力、异常掌控
                bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr6(), attributeType.getDisplayName());
                break;
            case SMALL_ATK:
                // 2号位：小攻击力
                bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr2(), attributeType.getDisplayName());
                break;
            case SMALL_DEF:
                // 3号位：小防御力
                bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr3(), attributeType.getDisplayName());
                break;
            case SMALL_HP:
                // 1号位：小生命值
                bonus += getDriveMainAttrValue(userConfig.getDriveMainAttr1(), attributeType.getDisplayName());
                break;
        }
        
        return bonus;
    }
    
    /**
     * 获取驱动盘随机属性加成
     */
    private double getDriveRandomAttrBonus(UserConfigDetailDto userConfig, AttributeType attributeType, boolean isPercentage) {
        double bonus = 0;
        
        // 所有6个位置的随机属性
        bonus += getDriveRandomAttrValue(userConfig.getDriveRandomAttr1(), attributeType.getDisplayName());
        bonus += getDriveRandomAttrValue(userConfig.getDriveRandomAttr2(), attributeType.getDisplayName());
        bonus += getDriveRandomAttrValue(userConfig.getDriveRandomAttr3(), attributeType.getDisplayName());
        bonus += getDriveRandomAttrValue(userConfig.getDriveRandomAttr4(), attributeType.getDisplayName());
        bonus += getDriveRandomAttrValue(userConfig.getDriveRandomAttr5(), attributeType.getDisplayName());
        bonus += getDriveRandomAttrValue(userConfig.getDriveRandomAttr6(), attributeType.getDisplayName());
        
        return bonus;
    }
    
    /**
     * 获取驱动盘主属性值
     */
    private double getDriveMainAttrValue(Map<String, Object> driveAttr, String key) {
        if (driveAttr == null || !driveAttr.containsKey(key)) return 0;
        Object value = driveAttr.get(key);
        if (value instanceof Number) {
            return ((Number) value).doubleValue();
        }
        return 0;
    }
    
    /**
     * 获取驱动盘随机属性值
     */
    private double getDriveRandomAttrValue(Map<String, Object> driveAttr, String key) {
        if (driveAttr == null || !driveAttr.containsKey(key)) return 0;
        Object value = driveAttr.get(key);
        if (value instanceof Number) {
            return ((Number) value).doubleValue();
        }
        return 0;
    }
} 